<template>
  <div ref="conversationListInnerDomRef" class="tui-conversation-list">
    <ActionsMenu v-if="isShowOverlay" :selectedConversation="currentConversation"
      :actionsMenuPosition="actionsMenuPosition" :selectedConversationDomRect="currentConversationDomRect"
      @closeConversationActionMenu="closeConversationActionMenu" />
    <div v-for="(conversation, index) in conversationList" :id="`convlistitem-${index}`" :key="index" :class="[
      'tui-conversation-content',
      isMobile && 'tui-conversation-content-h5 disable-select',
    ]" v-if="props.msgType == 'message'">
      <div :class="[
        isPC && 'isPC',
        'tui-conversation-item',
        currentConversationID === conversation.conversationID &&
        'tui-conversation-item-selected',
        conversation.isPinned && 'tui-conversation-item-pinned',
      ]" @click="enterConversationChat(conversation.conversationID)"
        @longpress="showConversationActionMenu($event, conversation, index)"
        @contextmenu="showConversationActionMenu($event, conversation, index, true)">
        <aside class="left">
          <Avatar useSkeletonAnimation :url="conversation.getAvatar()" size="50px" />
          <div v-if="userOnlineStatusMap && isShowUserOnlineStatus(conversation)" :class="[
            'online-status',
            Object.keys(userOnlineStatusMap).length > 0 &&
              Object.keys(userOnlineStatusMap).includes(
                conversation.userProfile.userID
              ) &&
              userOnlineStatusMap[conversation.userProfile.userID]
                .statusType === 1
              ? 'online-status-online'
              : 'online-status-offline',
          ]" />
          <span v-if="conversation.unreadCount > 0 && !conversation.isMuted" class="num">
            {{
            conversation.unreadCount > 99 ? "99+" : conversation.unreadCount
            }}
          </span>
          <span v-if="conversation.unreadCount > 0 && conversation.isMuted" class="num-notify" />
        </aside>
        <div class="content">
          <div class="content-header">
            <label class="content-header-label">
              <p class="name">{{ conversation.getShowName() }}</p>
            </label>
            <div class="middle-box">
              <span v-if="conversation.draftText && conversation.conversationID !== currentConversationID"
                class="middle-box-draft">{{ TUITranslateService.t('TUIChat.[草稿]') }}</span>
              <span v-else-if="
                conversation.type === 'GROUP' &&
                conversation.groupAtInfoList &&
                conversation.groupAtInfoList.length > 0
              " class="middle-box-at">{{ conversation.getGroupAtInfo() }}</span>
              <div class="middle-box-content">
                <template v-if="conversation.lastMessage.type == 'TIMCustomElem'">
                  <template v-if="JSON.parse(conversation.lastMessage.payload.data).type == 'evaluation'">{{
                    conversation.lastMessage.nick }}:[评价消息]</template>
                  <template v-if="JSON.parse(conversation.lastMessage.payload.data).type == 'workOrder'">
                    [工单动态消息]</template>
                  <template v-if="JSON.parse(conversation.lastMessage.payload.data).type == 'imgMsg'">{{
                    conversation.lastMessage.nick }}:[图文消息]</template>
                  <template v-if="JSON.parse(conversation.lastMessage.payload.data).type == 'docMsg'">{{
                    conversation.lastMessage.nick }}:[文件消息]</template>
                </template>
                <template v-else-if="conversation.lastMessage.type == 'TIMTextElem'">
                  {{ conversation.lastMessage.nick }}:
                  <template v-for="(item, idx) in getCustomEmoji(conversation.lastMessage.payload.text)" :key="idx">
                    <span v-if="item.name == 'text'">{{ item.text }}</span>
                    <img v-else :src="item.src" width="25" height="25" />
                  </template>
                </template>
                <template v-else>
                  {{ conversation.getLastMessage("text") }}
                </template>
              </div>
            </div>
          </div>
          <div class="content-footer">
            <span class="time">{{ conversation.getLastMessage("time") }}</span>
            <Icon v-if="conversation.isMuted" :file="muteIcon" />
            <!-- <span class="text" v-if="conversation.groupProfile.groupCustomField[0].value">{{
              JSON.parse(conversation.groupProfile.groupCustomField[0].value)[0].name }}</span> -->
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
interface IUserStatus {
  statusType: number;
  customStatus: string;
}

interface IUserStatusMap {
  [userID: string]: IUserStatus;
}
import { watch } from 'vue'
import { ref, onMounted, onUnmounted } from '../../../adapter-vue';
import TUIChatEngine, {
  TUIStore,
  StoreName,
  TUIConversationService,
  TUITranslateService,
  IConversationModel,
} from '@tencentcloud/chat-uikit-engine';
import TencentCloudChat from '@tencentcloud/chat';
import { TUIGlobal, isIOS, addLongPressListener } from '@tencentcloud/universal-api';
import Icon from '../../common/Icon.vue';
import Avatar from '../../common/Avatar/index.vue';
import ActionsMenu from '../actions-menu/index.vue';
import muteIcon from '../../../assets/icon/mute.svg';
import { isPC, isH5, isUniFrameWork, isMobile } from '../../../utils/env';
import { getTimeDifference, getSecondDifference, formatTimestampToTime } from '@/utils/format'
import { Chat } from '@/main';
import emojiData from '../../TUIChat/message-input-toolbar/emoji-picker/custom/emoji_data'
import { EMOJI_GROUP_LIST, BASIC_EMOJI_URL_MAPPING } from '../../TUIChat/emoji-config'
import { BASIC_EMOJI_NAME_TO_KEY_MAPPING } from '../../TUIChat/emoji-config/default-emoji'

const emits = defineEmits(['handleSwitchConversation', 'getPassingRef']);
const currentConversation = ref<IConversationModel>();
const currentConversationID = ref<string>();
const currentConversationDomRect = ref<DOMRect>();
const isShowOverlay = ref<boolean>(false);
const conversationList = ref<IConversationModel[]>([]);
const conversationList2 = ref<IConversationModel[]>([]);
const conversationListDomRef = ref<HTMLElement | undefined>();
const conversationListInnerDomRef = ref<HTMLElement | undefined>();
const actionsMenuPosition = ref<{
  top: number;
  left: number | undefined;
  conversationHeight: number | undefined;
}>({
  top: 0,
  left: undefined,
  conversationHeight: undefined,
});
const displayOnlineStatus = ref(false);
const userOnlineStatusMap = ref<IUserStatusMap>();

interface IProps {
  msgType: string;
}

const interval = ref(null);

const props = withDefaults(defineProps<IProps>(), {
  msgType: 'message'
});

let lastestOpenActionsMenuTime: number | null = null;

onMounted(() => {
  TUIStore.watch(StoreName.CONV, {
    currentConversationID: onCurrentConversationIDUpdated,
    conversationList: onConversationListUpdated,
    currentConversation: onCurrentConversationUpdated,
  });

  TUIStore.watch(StoreName.USER, {
    displayOnlineStatus: onDisplayOnlineStatusUpdated,
    userStatusList: onUserStatusListUpdated,
  });

  if (!isUniFrameWork && isIOS && !isPC) {
    addLongPressHandler();
  }

  // let onGroupAttributesUpdated = function (event: any) {
  //   const groupID = event.data.groupID // 群组ID
  //   const groupAttributes = event.data.groupAttributes // 更新后的群属性
  //   console.log(event.data);
  // };
  // Chat.on(TencentCloudChat.EVENT.GROUP_ATTRIBUTES_UPDATED, onGroupAttributesUpdated);
});

onUnmounted(() => {
  TUIStore.unwatch(StoreName.CONV, {
    currentConversationID: onCurrentConversationIDUpdated,
    conversationList: onConversationListUpdated,
    currentConversation: onCurrentConversationUpdated,
  });

  TUIStore.unwatch(StoreName.USER, {
    displayOnlineStatus: onDisplayOnlineStatusUpdated,
    userStatusList: onUserStatusListUpdated,
  });
});

watch(() => props.msgType, (New, Old) => {
  if (New == 'noreply') {
    // let list: any[] = []
    // conversationList.value.map((item: any) => {
    //   if (Number(item.lastMessage.fromAccount) > 0) {
    //     item.lastMessage.timeDifference = getTimeDifference(item.lastMessage.lastTime)
    //     list.push(item)
    //   }
    // })
    // conversationList2.value = list;
    getUnReplyList();
  } else {
    clearInterval(interval.value);
  }
})

function getCustomEmoji(message: string) {
  const reg = /(\[.+?\])/g;
  const emojiDataMap: { [key: string]: string } = {};
  emojiData.forEach(emoji => {
    emojiDataMap[emoji.key] = emoji.style;
  })
  const regex = /\[.*?\]|([^[\]]+)/g;
  let text: any[] = [];
  let match;
  while ((match = regex.exec(message)) !== null) {
    if (match[1]) {
      text.push({
        name: 'text',
        text: match[1]
      });
    } else {
      if (emojiDataMap[match[0]]) {
        match[0] = match[0].replace(reg, match => emojiDataMap[match] || match);
        text.push({
          emojiKey: match[0],
          name: 'img',
          src: `https://i.niuyuwang.com/emoji/${match[0]}.png`
        });
      } else if (BASIC_EMOJI_URL_MAPPING[match[0]]) {
        match[0] = match[0].replace(reg, match => BASIC_EMOJI_URL_MAPPING[match] || match);
        text.push({
          emojiKey: match[0],
          name: 'img',
          src: `${EMOJI_GROUP_LIST[0].url}/${match[0]}`
        });
      } else if (BASIC_EMOJI_NAME_TO_KEY_MAPPING[match[0]]) {
        match[0] = match[0].replace(reg, match => BASIC_EMOJI_NAME_TO_KEY_MAPPING[match] || match);
        match[0] = match[0].replace(reg, match => BASIC_EMOJI_URL_MAPPING[match] || match);
        text.push({
          emojiKey: match[0],
          name: 'img',
          src: `${EMOJI_GROUP_LIST[0].url}/${match[0]}`
        });
      } else {
        text.push({
          name: 'text',
          text: match[0]
        });
      }

    }
  }
  return text;
}

function getUnReplyList() {
  let list: any[] = [];
  conversationList.value.map((item: any) => {
    if (Number(item.lastMessage.fromAccount) > 0) {
      item.lastMessage.timeDifference = getTimeDifference(item.lastMessage.lastTime);
      item.lastMessage.seconds = getSecondDifference(item.lastMessage.lastTime);
      list.push(item);
    }
  })
  conversationList2.value = list;
  startTimer(conversationList2.value);
}

const startTimer = (list: any[]) => {
  interval.value = setInterval(() => {
    list.map((item: any) => {
      item.lastMessage.timeDifference = getTimeDifference(item.lastMessage.lastTime);
      item.lastMessage.seconds = getSecondDifference(item.lastMessage.lastTime);
    })
    conversationList2.value = list;
  }, 1000)
}

const isShowUserOnlineStatus = (conversation: IConversationModel): boolean => {
  return (
    displayOnlineStatus.value
    && conversation.type === TUIChatEngine.TYPES.CONV_C2C
  );
};

const showConversationActionMenu = (
  event: Event,
  conversation: IConversationModel,
  index: number,
  isContextMenuEvent?: boolean,
) => {
  if (isContextMenuEvent) {
    event.preventDefault();
    if (isUniFrameWork) {
      return;
    }
  }
  currentConversation.value = conversation;
  lastestOpenActionsMenuTime = Date.now();
  getActionsMenuPosition(event, index);
};

const closeConversationActionMenu = () => {
  // Prevent continuous triggering of overlay tap events
  if (
    lastestOpenActionsMenuTime
    && Date.now() - lastestOpenActionsMenuTime > 300
  ) {
    currentConversation.value = undefined;
    isShowOverlay.value = false;
  }
};

const getActionsMenuPosition = (event: Event, index: number) => {
  if (isUniFrameWork) {
    if (typeof conversationListDomRef.value === 'undefined') {
      emits('getPassingRef', conversationListDomRef);
    }
    const query = TUIGlobal?.createSelectorQuery().in(conversationListDomRef.value);
    query.select(`#convlistitem-${index}`).boundingClientRect((data) => {
      if (data) {
        actionsMenuPosition.value = {
          // The uni-page-head of uni-h5 is not considered a member of the viewport, so the height of the head is manually increased.
          top: data.bottom + (isH5 ? 44 : 0),
          // @ts-expect-error in uniapp event has touches property
          left: event.touches[0].pageX,
          conversationHeight: data.height,
        };
        isShowOverlay.value = true;
      }
    }).exec();
  } else {
    const rect = ((event.currentTarget || event.target) as HTMLElement)?.getBoundingClientRect() || {};
    if (rect) {
      actionsMenuPosition.value = {
        top: rect.bottom,
        left: isPC ? (event as MouseEvent).clientX : undefined,
        conversationHeight: rect.height,
      };
    }
    isShowOverlay.value = true;
  }
};

const enterConversationChat = (conversationID: string) => {
  emits('handleSwitchConversation', conversationID);
  TUIConversationService.switchConversation(conversationID);
};

function addLongPressHandler() {
  if (!conversationListInnerDomRef.value) {
    return;
  }
  addLongPressListener({
    element: conversationListInnerDomRef.value,
    onLongPress: (event, target) => {
      const index = (Array.from(conversationListInnerDomRef.value!.children) as HTMLElement[]).indexOf(target!);
      showConversationActionMenu(event, conversationList.value[index], index);
    },
    options: {
      eventDelegation: {
        subSelector: '.tui-conversation-content',
      },
    },
  });
}

function onCurrentConversationUpdated(conversation: IConversationModel) {
  currentConversation.value = conversation;
}

function onConversationListUpdated(list: IConversationModel[]) {
  conversationList.value = list;
  if (interval.value != null) {
    clearInterval(interval.value);
  }
  if (props.msgType === 'noreply') {
    getUnReplyList();
  }
  // conversationList2.value = []
  // list.forEach((item: any) => {
  //   if (Number(item.lastMessage.fromAccount) > 0) {
  //     item.lastMessage.timeDifference = getTimeDifference(item.lastMessage.lastTime)
  //     conversationList2.value.push(item)
  //   }
  // })
}

function topConversation(conversationID: string) {
  let promise = Chat.pinConversation({ conversationID: conversationID, isPinned: true });
  promise.then(function (imResponse) {
    // 置顶会话成功
  }).catch(function (imError) {
    console.warn('pinConversation error:', imError); // 置顶会话失败的相关信息
  });
}

function onCurrentConversationIDUpdated(id: string) {
  currentConversationID.value = id;
}

function onDisplayOnlineStatusUpdated(status: boolean) {
  displayOnlineStatus.value = status;
}

function onUserStatusListUpdated(list: Map<string, IUserStatus>) {
  if (list.size !== 0) {
    userOnlineStatusMap.value = [...list.entries()].reduce(
      (obj, [key, value]) => {
        obj[key] = value;
        return obj;
      },
      {} as IUserStatusMap,
    );
  }
}

// Expose to the parent component and close actionsMenu when a sliding event is detected
defineExpose({ closeChildren: closeConversationActionMenu });
</script>

<style lang="scss" scoped src="./style/index.scss"></style>
<style lang="scss" scoped>
.disable-select {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.time1 {
  margin-top: 3px;
  font-weight: bold;
  font-size: 12px;
}

.text {
  background-color: #f00;
  color: #fff;
  padding: 0 10px;
  font-size: 12px;
  height: 20px;
  line-height: 20px;
  border-radius: 10px;
}
</style>
